import { createRequire } from 'node:module';

import { nanoid } from 'nanoid';

import {
  fileStat,
  hasSubfolders,
  isSystemOrHiddenFolder,
  readDir,
} from '../../utils/index.mjs';

const require = createRequire(import.meta.url);
const fs = require('node:fs');
const path = require('node:path');

let isSearching = false; // 取消搜索token
export function createFolderHandler(app, logger) {
  // =================文件夹 Begin============================
  // 获取文件夹列表
  app.get('/folder/tree', async (req, res) => {
    const directory = req.query.path;
    const data = [];
    let result = { code: 200, msg: '获取成功' };
    try {
      const dirs = await fs.readdirSync(directory);
      for (const file of dirs) {
        try {
          const pathname = path.join(directory, file);
          if (isSystemOrHiddenFolder(pathname)) {
            data.push({
              id: nanoid(),
              isLeaf: !hasSubfolders(pathname),
              label: file,
              path: pathname,
            });
          }
        } catch (error) {
          logger.info(error);
          continue;
        }
      }
      result = {
        code: 200,
        data,
        msg: 'ok',
      };
    } catch (error) {
      logger.info(error);
      result = { code: 500, msg: '文件夹不存在' };
    } finally {
      res.send(result);
      res.end();
    }
  });

  // 获取文件夹下所有文件和文件夹信息
  app.get('/folder/list', async (req, res) => {
    const directory = req.query.path;
    const filter = req.query.filter || '';
    const data = [];
    let result = { code: 200, msg: '获取成功' };
    try {
      const items = fs.readdirSync(directory, { withFileTypes: true });
      for (const item of items) {
        try {
          if (item.name.startsWith('.') || item.name.startsWith(`$`)) {
            // 排除以.或$开头的文件夹
            continue;
          }
          const itemPath = path.join(directory, item.name);
          const stats = fs.statSync(itemPath);
          const isDirectory = item.isDirectory();
          if (
            filter &&
            !isDirectory &&
            !filter.includes(path.extname(item.name))
          )
            continue;
          const info = {
            checked: false,
            ext: isDirectory ? '' : path.extname(item.name) || '',
            fullPath: `${itemPath}`,
            mtime: stats.mtime,
            name: `${item.name}`,
            parentPath: `${directory}`,
            size: stats.size,
            type: isDirectory ? '2' : '1',
            url: isDirectory
              ? ''
              : `/webos-file/${itemPath.replaceAll('\\', '/')}`,
          };
          data.push(info);
        } catch (error) {
          logger.info(`/folder/list:${error}`);
          continue;
        }
      }

      // 默认按文件类型排序
      data.sort((a, b) => {
        let result = 0;
        if (a.type === '2' && b.type !== '2') {
          result = -1;
        } else if (a.type !== '2' && b.type === '2') {
          result = 1;
        }
        return result;
      });
      result = { code: 200, data, msg: 'ok' };
    } catch (error) {
      logger.info(error);
      result = { code: 500, msg: '文件夹不存在' };
    } finally {
      res.send(result);
      res.end();
    }
  });

  // 新建文件夹
  app.post('/folder/newFolder', (req, res) => {
    let result = { code: 200, msg: '新建文件夹成功' };
    let data = '';
    req.on('data', (chunk) => {
      data += chunk;
    });

    req.on('end', () => {
      try {
        data = JSON.parse(data); // 将JSON字符串解析成对象
        const name = data.name;
        const directory = data.path;

        const newPath = path.resolve(directory, name);
        let finalPath = newPath;
        let count = 0;
        logger.info(`newFolder newPath: ${newPath}`);

        while (fs.existsSync(finalPath)) {
          count++;
          finalPath = `${newPath} (${count})`;
        }
        logger.info(`newFolder: ${finalPath}`);
        fs.mkdir(finalPath, { recursive: true }, (err) => {
          if (err) {
            logger.error(`新建文件夹失败 ${file}:`, err);
          }
        });
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '新建文件夹失败' };
      } finally {
        res.send(result);
      }
    });
  });

  // 新建文件
  app.post('/folder/newFile', (req, res) => {
    let result = { code: 200, msg: '新建文件成功' };
    let data = '';
    req.on('data', (chunk) => {
      data += chunk;
    });

    req.on('end', async () => {
      try {
        data = JSON.parse(data); // 将JSON字符串解析成对象
        const name = data.name;
        const directory = data.path;

        const ext = path.extname(name);
        // 传入路径、拓展名，得到的是不带拓展名的文件名string
        const nameWithOutExt = path.basename(name, ext);
        const newPath = path.resolve(directory, nameWithOutExt);
        let finalPath = newPath + ext;
        let count = 0;
        logger.info(`finalPath newPath: ${newPath}`);

        while (fs.existsSync(newPath)) {
          count++;
          finalPath = `${newPath} (${count})${ext}`;
        }
        logger.info(`finalPath: ${finalPath}`);
        fs.writeFileSync(finalPath, '');
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '新建文件失败' };
      } finally {
        res.send(result);
      }
    });
  });
  // 删除文件夹或文件
  app.delete('/folder/delete', (req, res) => {
    let result = { code: 200, msg: '删除成功' };
    let data = '';
    req.on('data', (chunk) => {
      data += chunk;
    });
    req.on('end', () => {
      try {
        data = JSON.parse(data); // 将JSON字符串解析成对象
        data.forEach((item) => {
          fs.rmSync(item, { force: true, recursive: true });
        });
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '删除失败' };
      } finally {
        res.send(result);
        res.end();
      }
    });
  });

  // 重命名文件夹或文件
  app.post('/folder/rename', (req, res) => {
    let result = { code: 200, msg: '重命名成功' };
    let data = '';
    req.on('data', (chunk) => {
      data += chunk;
    });
    const errorFiles = [];
    req.on('end', () => {
      try {
        data = JSON.parse(data); // 将JSON字符串解析成对象
        const newName = data.name;
        const files = data.files;
        for (const file of files) {
          const newPath = path.resolve(path.dirname(file), newName);
          const ext = path.extname(file);
          let finalPath = newPath + ext;
          let count = 0;

          while (fs.existsSync(finalPath)) {
            count++;
            finalPath = `${newPath} (${count})${ext}`;
          }
          try {
            logger.info(`Renaming file ${file} to ${finalPath}`);
            fs.renameSync(file, finalPath, (err) => {
              if (err) {
                logger.error(`重命名失败 ${file}:`, err);
                errorFiles.push(file);
              }
            });
          } catch (error) {
            logger.info(error);
            continue;
          }
        }
        if (errorFiles.length > 0)
          result = {
            code: 200,
            data: errorFiles,
            msg: '重命名成功，存在错误文件',
          };
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '重命名失败' };
      } finally {
        res.send(result);
      }
    });
  });

  // 移动文件夹或文件
  app.post('/folder/moveto', (req, res) => {
    let result = { code: 200, msg: '移动成功' };
    let data = '';
    req.on('data', (chunk) => {
      data += chunk;
    });
    const errorFiles = [];
    req.on('end', () => {
      try {
        data = JSON.parse(data); // 将JSON字符串解析成对象
        const target = data.target;
        const files = data.files;
        for (const file of files) {
          const ext = path.extname(file);
          const newName = path.basename(file, ext);
          const newPath = path.resolve(target, newName);
          let finalPath = newPath + ext;
          let count = 0;

          while (fs.existsSync(finalPath)) {
            count++;
            finalPath = `${newPath} (${count})${ext}`;
          }
          try {
            logger.info(`Renaming file ${file} to ${finalPath}`);
            fs.renameSync(file, finalPath, (err) => {
              if (err) {
                logger.error(`移动失败 ${file}:`, err);
                errorFiles.push(file);
              }
            });
          } catch (error) {
            logger.info(error);
            continue;
          }
        }
        if (errorFiles.length > 0)
          result = {
            code: 200,
            data: errorFiles,
            msg: '移动成功，存在错误文件',
          };
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '移动失败' };
      } finally {
        res.send(result);
      }
    });
  });

  // 搜索文件夹或文件
  async function searchDirectory(directory, keyword, data) {
    const files = await readDir(directory, { withFileTypes: true });

    for (const file of files) {
      if (!isSearching) {
        break; // 如果isSearching为false，立即终止递归搜索
      }
      if (file.name.startsWith('.') || file.name.startsWith(`$`)) {
        // 排除以.或$开头的文件夹
        continue;
      }
      try {
        const filePath = path.join(directory, file.name);
        const stats = await fileStat(filePath);

        const isDirectory = stats.isDirectory();

        const info = {
          checked: false,
          ext: isDirectory ? '' : path.extname(file.name) || '',
          fullPath: `${filePath}`,
          mtime: stats.mtime,
          name: `${file.name}`,
          parentPath: `${directory}`,
          size: stats.size,
          type: isDirectory ? '2' : '1',
        };
        if (isDirectory) {
          // 检查文件夹名是否包含关键字
          if (file.name.includes(keyword)) {
            data.push(info);
          }
          await searchDirectory(filePath, keyword, data); // 递归搜索子文件夹
        } else if (stats.isFile() && file.name.includes(keyword)) {
          // 检查文件名或文件内容是否包含关键字
          data.push(info);
        }
      } catch (error) {
        logger.info(error);
        continue;
      }
    }
  }
  app.post('/folder/search', (req, res) => {
    let result = { code: 200, msg: '搜索成功' };
    let body = '';
    req.on('data', (chunk) => {
      body += chunk;
    });

    const data = [];
    req.on('end', async () => {
      try {
        body = JSON.parse(body); // 将JSON字符串解析成对象
        const keyword = body.keyword;
        const directory = body.path;
        isSearching = true;
        await searchDirectory(directory, keyword, data);
        result = { code: 200, data, msg: 'ok' };
      } catch (error) {
        logger.info(error);
        result = { code: 500, msg: '搜索失败' };
      } finally {
        isSearching = false;
        res.send(result);
      }
    });
  });
  // 取消恢复搜索
  app.get('/folder/resume', (req, res) => {
    isSearching = false;
    res.send({ code: 200, msg: '取消搜索成功' });
    res.end();
  });

  // =================文件夹 End============================
}
